#ifndef SERVER_ENTRY_H_
#define SERVER_ENTRY_H_

#include <map>
#include <strings.h>
#include <string.h>
#include "ct_mutex.h"
#include "command.h"

#define MAX_SERVERNAME 32

struct ServerEntryNew
{
        WORD wdID;
        WORD wdType;
        WORD wdNet;
        DWORD dwLoad;
        char strName[MAX_SERVERNAME];
        char strIPInner[MAX_IP_LENGTH];
        char strIPListen[MAX_IP_LENGTH];
        char strIPConnect[MAX_IP_LENGTH];
        WORD wdPort;

        ServerEntryNew()
        {
                wdID    = 0;
                wdType  = 0;
                wdNet   = 0;
                dwLoad  = 5000;
                bzero(strName, sizeof(strName));
                bzero(strIPInner, sizeof(strIPInner));
                bzero(strIPListen, sizeof(strIPListen)); 
                bzero(strIPConnect, sizeof(strIPConnect));
                wdPort  = 0;
        }
        ServerEntryNew(const WORD &serverid,
                        const WORD &servertype,
                        const WORD &nettype,
                        const DWORD &serverload,
                        const std::string &servername,
                        const std::string &innerip,
                        const std::string &listenip,
                        const std::string &connectip,
                        const DWORD &listenport)
        {
                wdID    = serverid;
                wdType  = servertype;
                wdNet   = nettype;
                dwLoad  = serverload;
                strncpy(strName,      servername.c_str(), MAX_SERVERNAME);
                strncpy(strIPInner,   innerip.c_str(),    MAX_IP_LENGTH);
                strncpy(strIPListen,  listenip.c_str(),   MAX_IP_LENGTH);
                strncpy(strIPConnect, connectip.c_str(),  MAX_IP_LENGTH);
                wdPort  = listenport;
        }
        ServerEntryNew(const ServerEntryNew &se)
        {
                wdID    = se.wdID;
                wdType  = se.wdType;
                wdNet   = se.wdNet;
                dwLoad  = se.dwLoad;
                strncpy(strName,      se.strName,      MAX_SERVERNAME);
                strncpy(strIPInner,   se.strIPInner,   MAX_IP_LENGTH);
                strncpy(strIPListen,  se.strIPListen,  MAX_IP_LENGTH);
                strncpy(strIPConnect, se.strIPConnect, MAX_IP_LENGTH);
                wdPort  = se.wdPort;
        }
        ServerEntryNew &operator = (const ServerEntryNew &se)
        {
                if (this != &se) {
                        wdID    = se.wdID;
                        wdType  = se.wdType;
                        wdNet   = se.wdNet;
                        dwLoad  = se.dwLoad;
                        strncpy(strName,      se.strName,      MAX_SERVERNAME);
                        strncpy(strIPInner,   se.strIPInner,   MAX_IP_LENGTH);
                        strncpy(strIPListen,  se.strIPListen,  MAX_IP_LENGTH);
                        strncpy(strIPConnect, se.strIPConnect, MAX_IP_LENGTH);
                        wdPort  = se.wdPort;
                }
                return *this;
        }
        WORD getID() const
        {
                return wdID;
        }
        WORD getType() const
        {
                return  wdType;
        }
        WORD getNet() const
        {
                return wdNet;
        }
        DWORD getLoad() const
        {
                return dwLoad;
        }
        const char *getName() const
        {
                return strName;
        }
        const char *getIPInner() const
        {
                return strIPInner;
        }
        const char *getIPListen() const
        {
                return strIPListen;
        }
        const char *getIPConnect() const
        {
                return strIPConnect;
        }
        DWORD getPort() const
        {
                return wdPort;
        }
};

typedef std::map<WORD, ServerEntryNew> ServerList;
typedef ServerList::iterator ServerList_IT;

class ServerEntryManager
{
        public:
                void addServerEntry(ServerEntryNew se)
                {
                        lock.lock();
                        server_entry_list_[se.getID()] = se;
                        lock.unlock();
                }
                void delServerEntry(ServerEntryNew &se)
                {
                        lock.lock();
                        server_entry_list_.erase(se.getID());
                        lock.unlock();
                }
                const ServerEntryNew *getServerEntryById(const WORD &id)
                {
                        lock.lock();
                        ServerList_IT it = server_entry_list_.find(id);
                        if (it != server_entry_list_.end()) {
                                lock.unlock();
                                return &(it->second);
                        }
                        lock.unlock();
                        return NULL;
                }
                bool getServerEntryById(const WORD &id, ServerEntryNew &entry)
                {
                        lock.lock();
                        ServerList_IT it = server_entry_list_.find(id);
                        if (it != server_entry_list_.end()) {
                                lock.unlock();
                                entry = it->second;
                                return true;
                        }
                        lock.unlock();
                        return false;
                }
                void getServerEntryByType(const WORD &type, ServerList &list)
                {
                        lock.lock();
                        for(ServerList_IT it = server_entry_list_.begin(); 
                                        it != server_entry_list_.end(); 
                                        ++it) {
                                if(it->second.getType() == type) {
                                        list[it->first] = it->second;
                                }
                        }
                        lock.unlock();
                }
                void getAllServerEntry(ServerList &list)
                {
                        lock.lock();
                        list = server_entry_list_;
                        lock.unlock();
                }
                DWORD getServerLoad(const WORD &id)
                {
                        DWORD ret = 0;
                        lock.lock();
                        ServerList_IT it = server_entry_list_.find(id);
                        if (it != server_entry_list_.end()) {
                                ret = it->second.getLoad();
                        }
                        lock.unlock();
                        return ret;
                }
                void clear()
                {
                        lock.lock();
                        server_entry_list_.clear();
                        lock.unlock();
                }
        private:
                ServerList server_entry_list_;
                ctMutex lock;
};

#endif
